通过 Vue.extend 封装JS组件

MuYan2021-10-29VueVue

Vue-extend 文档open in new window

注:

  • 以 Ant Design of Vue UI 库的 Modal 对话框二次封装为例子,配置成功后可直接 js 调用,也可按照原有 components 引入调用。

  • components 引入调用不做相关示例说明,Modal 对话框只是作为示例,可自定义组件,也可二次封装其他 UI 库组件。

  • 先自定义相关组件

<!-- components/mModal/mModal.vue -->
<template>
  <div>
    <a-modal
      :title="title"
      :visible="visible"
      :footer="null"
      @cancel="cancel"
      :width="`${width}px`"
    >
      <div :style="[contentStyle]" class="text-wrap m-modal-content-wrap">
        <span>
          <span>
            <a-icon
              :type="iconType"
              v-if="icon"
              theme="filled"
              :style="[
                {
                  color: '#F19423',
                  fontSize: '25px',
                  marginRight: '12px',
                  ...iconStyle,
                },
              ]"
              class="m-modal-tips"
            />
          </span>
          <span v-html="content"></span>
        </span>
      </div>
      <div class="m-modal-footer-wrap" v-if="footer">
        <a-button v-if="cancelShow" @click="cancel">{{ cancelText }}</a-button>
        <a-button type="primary" @click="ok">
          {{ okText }}
        </a-button>
      </div>
    </a-modal>
  </div>
</template>

<script>
export default {
  name: "mModal",
  data() {
    return {
      title: "标题",
      content: "",
      visible: false,
      cancelText: "取消",
      okText: "确定",
      cancelShow: false,
      width: 600,
      contentStyle: {},
      footer: true,
      iconType: "exclamation-circle",
      icon: false,
      iconStyle: {},
    };
  },
  mounted() {},
  methods: {
    show(
      obj = {
        title: "测试",
        content: "测试",
      }
    ) {
      // 组件的配置参数信息
      for (let i in obj) {
        if (this[i] != undefined) this[i] = obj[i];
      }
      this.$nextTick(() => {
        this.visible = true;
      });
    },
    hide() {
      this.visible = false;
      // 使用 setTimeout,减少移除的违和感
      setTimeout(() => {
        // 移除 DOM,释放内存
        this.$destroy(true);
        this.$el.parentNode.removeChild(this.$el);
      }, 500);
    },
    cancel() {
      this.hide();
    },
    ok() {
      this.hide();
    },
  },
};
</script>
<style lang="less" scoped>
::v-deep {
  .ant-modal-title {
    font-size: 20px;
    font-weight: bold;
  }
  .ant-modal-body {
    overflow: hidden;
  }
}
.m-modal-content-wrap {
  min-height: 100px;
  .m-modal-tips {
    position: relative;
    vertical-align: text-top;
  }
}
.m-modal-footer-wrap {
  display: flex;
  align-content: center;
  justify-content: center;
  padding-top: 24px;
  margin-top: 24px;
  position: relative;

  &::after {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    border-top: 1px solid #eeeeee;
    width: calc(200%);
    top: 0;
    content: "";
  }
  ::v-deep {
    .ant-btn {
      width: 200px;
      height: 40px;
      font-size: 16px;
    }
    .ant-btn + .ant-btn {
      margin-left: 20px;
    }
  }
}
</style>
  • 配置 Vue.extend 相关文件信息
// components/mModal/index.js
import modal from "./mModal.vue";
import Vue from "vue";

let obj = (
  data = {
    title: "",
    content: "",
  }
) => {
  // 通过 Promise 实现 组件内部方法的(重定义) callback 回调
  return new Promise((resolve, reject) => {
    // 创建构造器
    let mModal = Vue.extend(modal);
    // 创建 newModal 实例
    let newModal = new mModal();
    // 挂载到一个元素上
    let vm = newModal.$mount();
    // 获取 newModal 内容
    let el = vm.$el;
    // 将创建的 newModal 添加到 body 尾部
    document.body.appendChild(el);
    // 调用组件内部 show 方法,并传入组件自定义参数
    newModal.show(data);
    newModal.ok = () => {
      newModal.hide();
      resolve();
    };
    newModal.cancel = () => {
      newModal.hide();
      reject();
    };
  });
};

export default obj;
  • 组件引入
// main.js
import Vue from "vue";
import mModal from "@/components/mModal";
Vue.prototype.$mModal = mModal;
  • 组件调用。
// 具体配置参数根据自己组件内的 data 相关定义传参
this.$mModal({
  title: "提示",
  content: `具体内容`,
  okText: "我知道了",
})
  .then(() => {
    // 点击了确定按钮
  })
  .catch(() => {
    // 点击了取消按钮
  });
上次更新 2026/6/23 11:49:15
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8